package model.database;

import java.io.OutputStream;
import java.sql.ResultSet;
import java.sql.SQLXML;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;



import model.configuration.ConfigData;
import model.xml.SerializeObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


public class ObjectDataProvider {
	
	private static final Logger localLoger = LogManager.getLogger(ObjectDataProvider.class.getClass());
	
	/**
	 * Send some object to database and get some object from database.
	 * @param inObject Object will serialize to XML and store or point how to get data in database. 
	 * @param pClass class of returned object
	 * @param storedProcedure Store procedure name for call
	 * @return Object deserilized from XML returned from stored procedure
	 * @throws Exception
	 */
	public static Object sendObject2GetObject(Object inObject,Class pClass, String storedProcedure) throws Exception {
		Object result;
		
		localLoger.trace(ConfigData.METHOD_START_TEXT);
		CallStatement callStatement = new CallStatement(storedProcedure, SerializeObject.serializeToOutputStream(inObject), Types.SQLXML, Types.SQLXML);
		callStatement.execute();
		SQLXML sqlxml = callStatement.returnInOutDataXml(); // get xml data
		SQLXML outSql = callStatement.returnOutDataXml();   // get xml returned status of database call
		callStatement.close(); //good guy close
		callStatement.commitTransaction();//commit transaction
		callStatement.closeConnection(); //return connection to connection pool or close
		// check status of storeprocedure call
		CallStatus callStatus = (CallStatus)SerializeObject.deSerializeFromXml(CallStatus.class, outSql);
		if (callStatus.getStatusCode() != ConfigData.CODESUCCESS) {
			throw new Exception("Can't save object "+pClass.getName()+". Status Code: " + callStatus.getStatusCode() 
					+ "; Status Message: " + callStatus.getStatusMessage() );}
		result = SerializeObject.deSerializeFromXml(pClass, sqlxml);
		localLoger.trace(ConfigData.METHOD_END_TEXT);
		return result;
		
	}
	
	/**
	 * Send object to database and get list objects from database
	 * @param inObject Object for send. Object serialize to xml and parse in database to filter returned data
	 * @param pClass Returned Class List
	 * @param storedProcedure Stored procedured processes operation in database 
	 * @return
	 * @throws Exception
	 */
	public static List sendObject2GetListObject(Object inObject, Class pClass, String storedProcedure) throws Exception{
		localLoger.trace(ConfigData.METHOD_START_TEXT);
		List result = new ArrayList(); //Class have stored in array unknown
		final int sqlXmlNumberInResultSet = 1; // Number of column in result set
		final int fetchSize = 50; //Count record transfered in one time
		//1. Call stored procedure and get data
		CallStatement callStatement = new CallStatement(storedProcedure, SerializeObject.serializeToOutputStream(inObject), Types.OTHER, Types.SQLXML);
		callStatement.getCallableStatement().setFetchSize(fetchSize);
		//2. Get Result Set
		callStatement.execute();
		ResultSet resultSet = callStatement.returnResultSet();
		//3. Loop through result set
		while(resultSet.next()) {
			result.add(SerializeObject.deSerializeFromXml(pClass, resultSet.getSQLXML(sqlXmlNumberInResultSet)));
		}
		//4. Close result set.
		resultSet.close();
		callStatement.close();
		callStatement.commitTransaction();
		callStatement.closeConnection();
		localLoger.trace(ConfigData.METHOD_END_TEXT);		
		return result;
	}
	
}
